package com.oitsm.plugins.snmp;

import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import com.oitsm.plugin.entity.Context;
import com.oitsm.plugin.entity.Meta;
import com.oitsm.plugin.entity.PluginMeta;
import com.oitsm.plugin.entity.Response;
import com.oitsm.plugin.interfaces.Plugin;
import com.oitsm.plugin.service.PluginMetaService;
import com.oitsm.utils.Str2Num;

/**
 * SNMP采集器
 * @author Arab Runner
 * Jul 17, 2011 10:54:46 AM
 */
public class SNMPMonitor implements Plugin {
	public static final int VERSION_2C = SnmpConstants.version2c;
	public static final int VERSION_1 = SnmpConstants.version1;
	public static final int VERSION_3 = SnmpConstants.version3;
	
	private String ip = null;
	private int port = 161;
	private int version = VERSION_2C;
	
	private int timeout = 1500;
	private int retry = 2;

	private Snmp snmp;
	private Address targetAddress;
	private CommunityTarget target;

	/**
	 * 执行采集
	 */
	@SuppressWarnings("unchecked")
	public void excute(PluginMeta meta,Context ctx, Response out) throws Exception {
		try{
			init(ctx);
			
			PDU request = new PDU();         
			request.setType(PDU.GET);   
			
			Map<String,String> mapping = new HashMap<String,String>();
			for(Meta rm : meta.getConstants()){
				if(rm.getName().startsWith("OID:")){
					String name = rm.getName().substring(4);
					String oid = rm.getValue();
					request.add(new VariableBinding(new OID(oid)));
					mapping.put(oid, name);
				}
			}
			
//			request.add(new VariableBinding(new OID(".1.3.6.1.2.1.1.1.0")));
			PDU response = null;//定义response包
			
	        ResponseEvent responseEvent = snmp.send(request, target); //发出request PDU
	        //接收response PDU
	        response = responseEvent.getResponse();
	        if(response==null){
	        	out.setFailure("No SNMP response from remote host!");
	        }else if(response.getErrorIndex()==PDU.noError&&response.getErrorStatus()==PDU.noError){
	        	Vector<VariableBinding> vs = response.getVariableBindings();
	        	for(VariableBinding v : vs){
	        		String name = mapping.get(v.getOid().toString());
	        		out.add(name, v.getVariable().toString(), null);
	        	}
	        	out.setSuccess(true);
	    	}else{
	    		out.setFailure("SNMP response error,msg:"+response.getErrorStatusText());
	    	}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(snmp!=null){
				snmp.close();
			}
		}
	}
	
	/**
	 * 初始化
	 * @param ctx
	 * @throws Exception
	 */
	private void init(Context ctx)throws Exception{
		ip = ctx.getProp("host");
		port = Str2Num.parseInt(ctx.getProp("port"), port);
		timeout = Str2Num.parseInt(ctx.getProp("timeout"), timeout);
		retry = Str2Num.parseInt(ctx.getProp("retry"), retry);
		
		version = parseVersion(ctx.getStrAttr("snmpVersion"));

		snmp = new Snmp(new DefaultUdpTransportMapping());
		targetAddress = new UdpAddress(ip+"/"+port);
		
		target = new CommunityTarget();//
		target.setVersion(version);//
		target.setAddress(targetAddress);
		target.setCommunity(new OctetString("public"));
		
		target.setTimeout(timeout);
		target.setRetries(retry);
		
		snmp.listen();     
	}

	private int parseVersion(String v) {
		if (v == null) {
			return VERSION_2C;
		}else if(v.equals("2c")){
			return VERSION_2C;
		}else if(v.equals("1")){
			return VERSION_1;
		}else if(v.equals("3")){
			return VERSION_3;
		}
		return VERSION_2C;
	}

	public static void main(String[] args) throws Exception {
		PluginMetaService.init();
		
		SNMPMonitor m = new SNMPMonitor();
		Map<String, String> props = new HashMap<String, String>();
		props.put("ip", "192.168.91.129");

		Response out = new Response();
		Context ctx = new Context(props);

		m.excute(PluginMetaService.getPluginMeta("host.cpu.snmp"),ctx, out);
		System.out.println(out.toString());
	}
}
